home *** CD-ROM | disk | FTP | other *** search
- Subject: v25i036: listserv5.31 - mailing list management system, Part02/06
- Newsgroups: comp.sources.unix
- Approved: vixie@pa.dec.com
-
- Submitted-By: tasos@cs.bu.edu
- Posting-Number: Volume 25, Issue 36
- Archive-Name: listserv5.31/part02
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 6)."
- # Contents: src/README src/defs.h src/sender.c src/serverd.c
- # src/start.c src/sysmail.c src/sysmail.h
- # Wrapped by vixie@cognition.pa.dec.com on Fri Dec 13 18:31:08 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'src/README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/README'\"
- else
- echo shar: Extracting \"'src/README'\" \(9846 characters\)
- sed "s/^X//" >'src/README' <<'END_OF_FILE'
- X
- X
- X DISCUSSION LIST SERVER SYSTEM
- X -----------------------------
- X
- X Copyright (c) 1991, Anastasios C. Kotsikonas
- X
- X tasos@cs.bu.edu
- X Boston University
- X December 9 1991
- X
- AGREEMENT: This software can be used and distributed freely as long as you
- do not remove or alter the Copyright notice in the file defs.h; this notice
- is #define'd in the symbol VERSION. By using this software you are bound
- by this agreement.
- This software comes with no warranties and cannot be sold for profit.
- The AGREEMENT and COPYRIGHT notices should be included in all source
- files when distributing this software.
- COPYRIGHT: Copyright (c) 1991, Anastasios C. Kotsikonas
- X
- UPDATES: All updates can be obtained from cs.bu.edu (128.197.10.1) via
- anonymous ftp, in the directory pub/listserv. If you downloaded this version
- from another ftp site, please keep an eye on cs.bu.edu. Bug fixes will
- be posted periodically over there, and no notifications will be posted to
- news; you should check the directory periodically.
- X
- COMPILER: The programs are written with ANSI C function prototypes; if your
- compiler cannot handle them, I suggest you also download unproto.tar.Z
- from cs.bu.edu; cd pub/unproto; this is a nice set of programs that will
- convert ANSI-isms to old style C -- please send any questions about unproto
- to its author, not me. There is also a script (oldc -- found in pub/utils)
- that will step through all of its input files and use unproto to make the
- conversions. For those compilers that die when they see a contol-L in the
- source code, I have written a C program that "cleans" source files; it is
- called clean.c and can be found in pub/utils as well; compile as follows:
- X % cc -Dunix clean.c -o clean
- X
- PREPROCESSOR: ANSI C preprocessors complain about the way I concatenate
- strings (as is the case with the PATH symbol). This is expected since I
- do not conform to ANSI C in this respect. In this case you should
- use the script /usr/server/stds; suggested usage is:
- X % stds /usr/server/src/*.h /usr/server/src/*.c
- Use this script before compilation, of course. Unfortunately, I cannot
- convert to ANSI C string concatenation, because unproto does not work in
- this case, and people without ANSI C compilers will be in a lot of trouble.
- X
- ACKNOWLEDGEMENTS: I would like to thank the following people for their
- suggestions and contributions to this package (not all suggestions have
- been incorporated):
- X1) Bob Boyd (rbn@epavax.rtpnc.epa.gov): IRIX port, gateway connections
- X feedback, 5.3 beta testing.
- X2) Stefan Schroer (Stefan.Schroer@cyber.urz.uni-wuppertal.dbp.de): MINIX port,
- X help files, 'get' and 'index' requests.
- X3) Scott J. Ellentuch (tuc@stormking.com): IBM R6000 port, enhancements to
- X the farch utility, 5.3 beta testing.
- X4) David Warner (warner@austin.onu.edu): IBM R6000 bug fixing, 5.3 beta
- X testing, tolerance with my obnoxious code -- I owe this gentleman a lot.
- X
- X The discussion list server system includes 65 files:
- X
- X /usr/server/doc:
- X server.nr -- the man page for the system (% more server.nr)
- X farch.nr -- the man page for the file archiving utility
- X queue.nr -- the man page for tha mail queueing system
- X README -- instructions for installing the man pages on your system
- X
- X /usr/server/help:
- X general -- general help file
- X information -- help on the information request
- X lists -- help on the lists request
- X recipients -- help on the recipients request
- X set -- help on the set request
- X statistics -- help on the statistics request
- X subscribe -- help on the subscribe request
- X unsubscribe -- help on the unsubscribe request
- X index -- help on the index request
- X get -- help on the get request
- X release -- help on the release request
- X
- X /usr/server/archives:
- X /usr/server/archives/listserv: Master archive:
- X DIR -- info on files and directories they are located
- X INDEX -- master index of all archives (listserv, pub, unix)
- X refcard -- list of all commands
- X info -- info on this archive
- X /usr/server/archives/listserv/example.dat:
- X example.dat1 -- part 1 of file example.dat in archive listserv
- X example.dat2 -- part 2 of file example.dat in archive listserv
- X example.dat3 -- part 3 of file example.dat in archive listserv
- X /usr/server/archives/pub: Subarchive of listserv:
- X DIR -- info on files and directories they are located
- X INDEX -- index of all archives in this archive
- X info -- info on this archive
- X /usr/server/archives/pub/unix: Subarchive of pub:
- X DIR -- info on files and directories they are located
- X INDEX -- index of files in this archive
- X info -- info on this archive
- X
- X /usr/server/src:
- X REGISTRATION -- registration form for using this software
- X README -- this file
- X global.h -- global variables definitions
- X struct.h -- defines the server structure
- X defs.h -- general definitions
- X tlock.c -- tests for locks, i.e. whether any server programs are running
- X on another file system via NFS
- X list.h -- specific definitions for list.c
- X list.c -- the list's server
- X listserv.h -- specific definitions for listserv.c
- X listserv.c -- server for individual requests
- X pqueue.h -- specific definitions for pqueue.c
- X pqueue.c -- processes the mail queue
- X serverd.h -- specific definitions for serverd.c
- X serverd.c -- parent program that spawns list or listserv
- X start.h -- specific definitions for start.c
- X start.c -- does housekeeping before spawning serverd, makes sure that
- X files exist, kills any running server processes, etc
- X sysmail.h -- specific definitions for sysmail.c
- X sysmail.c -- system mailmethod routines
- X signals.c -- signal processing routines
- X sender.c -- sender address manipulation routines
- X misc.c -- general purpose routines
- X farch.c -- utility for easy archiving of files
- X Makefile -- to build your own server
- X
- X /usr/server
- X setup -- a script to be run before starting for the first time
- X queued -- daemon controlling the processing of the mail queue
- X peer -- script to add a peer list
- X news -- script to add a news group to a list
- X reformat -- script used to reformat incoming messages (see documentation)
- X stds -- script used to do string concatenation before compilation
- X redux -- script that reduces the size of mbox by removing unnecessary
- X fields from the header of each message
- X ulock -- in conjunction with the 'flocks' file, this utility
- X removes all locked files (unlocks them)
- X flocks -- shell script to remove locked files
- X .awk -- awk program used for the 'statistics' and 'recipients'
- X listserv requests
- X .stats -- shell script used for the 'statistics' listserv request
- X .grep -- shell program used for the 'statistics' listserv request
- X .ignored -- a list of email addresses whose messages are ignored
- X config -- the system's configuration file
- X
- X
- X |-->-----------> START
- X | |
- X | |
- X ^ (spawns-and-dies)
- X | |
- X | |
- X |--<--restart--- SERVERD <--shutdown-<--|
- X /\ r
- X / \ e
- X / \ s
- X (spawns either one as necessary) t
- X / \ a
- X / \ r
- X LIST LISTSERV --->---t
- X
- X
- The diagram shows that 'start' spawns 'serverd' and then dies, and that
- X'listserv' may request 'serverd' to die (shutdown) or request that the
- system is restarted, in which case 'serverd' spawns 'start' and dies.
- X
- XEnjoy!
- X
- Revision history:
- X
- Version Date Status Comments
- X------------------------------------------------------------------------------
- X 3.45 12/20/90 Outdated * First public version; bugs with listserv
- X 3.67 01/03/91 Outdated Bugs fixed
- X 3.68 01/04/91 Outdated * v3.67 + tlock utility
- X 4.0 04/09/91 Exprmntl v3.68 + STATISTICS listserv command
- X 4.1 04/16/91 Outdated v4.0 + redux utility
- X 4.2 05/02/91 Outdated v4.1 w/ optimized source code, better doc.
- X 4.21 05/03/91 Outdated v4.2 w/ redux which was left out by mistake
- X 4.3 05/03/91 Outdated * v4.21 w/ better mailer-daemon msg handling
- X 4.4 05/22/91 Exprmntl v4.3 w/ enhanced tlock,control,start,listserv
- X 4.5 06/12/91 Exprmntl v4.3 w/ enhanced listserv
- X 5.0 07/17/91 Outdated * v4.4 + support for multiple lists
- X 5.1 08/27/91 Outdated * v5.0 + bug fixes, enhanced listserv
- X 5.1 Rev I 10/03/91 Outdated v5.0 + more bug fixes
- X 5.2 10/08/91 Outdated * v5.1 + archives, GET, INDEX requests,
- X farch utility, moderated lists,
- X disabled listserv commands on a per list
- X basis, link with peer lists and news
- X feeds
- X 5.2 Rev A 10/10/91 Outdated v5.2 + bug fixes
- X 5.21 10/15/91 Exprmntl v5.2A + multiple recipients in one message
- X 5.3 beta 10/31/91 Exprmntl v5.21 + system mailmethod, bug fixes
- X 5.3 12/05/91 Outdated * v5.2A + bug fixes, universal system mailmethod,
- X multiple recipients in one message,
- X support for blanks in email addresses,
- X user-set limit on size of messages,
- X RFC 821 compliant SMTP implementation,
- X extensive mail loop detection mechanism,
- X new scripts (stds, reformat), enhanced
- X GET request, and more.
- X 5.31 12/09/91 Released * v5.3 + mail queuing capability/subsystem +
- X RELEASE request
- X
- X*These versions have been made public via news.
- END_OF_FILE
- if test 9846 -ne `wc -c <'src/README'`; then
- echo shar: \"'src/README'\" unpacked with wrong size!
- fi
- # end of 'src/README'
- fi
- if test -f 'src/defs.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/defs.h'\"
- else
- echo shar: Extracting \"'src/defs.h'\" \(4982 characters\)
- sed "s/^X//" >'src/defs.h' <<'END_OF_FILE'
- X/*
- X AGREEMENT: This software can be used and distributed freely as long
- X as you do not remove or alter the Copyright notice in this file;
- X this notice is #define'd in the symbol VERSION. Although you may alter
- X the code provided, you may not alter the functions create_header()
- X and create_multi_recipient_header() in list.c and listserv.c.
- X By using this software you are bound by this agreement.
- X This software comes with no warranties and cannot be sold for profit.
- X The AGREEMENT and COPYRIGHT notices should be included in all source
- X files when distributing this software.
- X COPYRIGHT: Copyright (c) 1991, Anastasios C. Kotsikonas
- X
- X General system definitions.
- X
- X WARNING: Do not use the gcc preprocessor.
- X
- X WARNING: DO NOT CHANGE THE NAME OF THE 'SERVERD', 'LIST' or 'LISTSERV'
- X PROGRAMS in the #define's below. If you do so, make sure that command line
- X options are separated by at least a space from the filename.
- X DO NOT INCLUDE ANY CHARACTERS SUCH AS &, |, <, >. etc.
- X
- X Preserve any quotes and new lines that appear below; change only path names.
- X
- X ALWAYS SPECIFY ABSOLUTE PATHS.
- X
- X*/
- X
- X#define VERSION "5.31 -- Copyright (c) 1991, Anastasios Kotsikonas"
- X#define PATH "/usr/server
- X#define COMPLETE_FILE(f) fprintf (f, "\n.\nQUIT\n")
- X#define TELNET "telnet `hostname` 25 > /dev/null 2>&1 "
- X#define BINMAIL "/bin/mail > /dev/null 2>&1"
- X#define INEWS "/usr/lib/news/inews"
- X#define SUBSCRIBERS ".subscribers"
- X#define ALIASES ".aliases"
- X#define NEWSF ".news"
- X#define PEERS ".peers"
- X#define HEADERS ".headers"
- X#define RESTRICTED ".restricted"
- X#define IGNORED ".ignored"
- X#define INFO_FILE ".info"
- X#define WELCOME_FILE ".welcome"
- X#define REPORT_LIST ".report.list"
- X#define WARNING PATH/.warning"
- X#define REPORT_SERVER PATH/.report.server"
- X#define REPORT_SERVERD PATH/.report.daemon"
- X#define REPORT_PQUEUE PATH/.report.pqueue"
- X#define CONFIG PATH/config"
- X#define LIST PATH/list -1 -L "
- X#define SERVER PATH/listserv -1 "
- X#define LIST_MAIL_FILE "mail"
- X#define LIST_MODERATED_F "moderated"
- X#define MESSAGE_IDS_F ".message.ids"
- X#define SERVER_MAIL_FILE PATH/requests"
- X#define SERVERD PATH/serverd"
- X#define PQUEUE PATH/pqueue"
- X#define START PATH/start"/* Do not give ANY command line options */
- X#define START_OPTIONS "-cr" /* provide them here */
- X#define SERVERD_LOCK_FILE PATH/.lock.serverd"
- X#define LIST_LOCK_FILE PATH/.lock.list"
- X#define SERVER_LOCK_FILE PATH/.lock.server"
- X#define PQUEUE_LOCK_FILE PATH/.lock.pqueue"
- X#define PID_PQUEUE PATH/.pid.pqueue"
- X#define PID_SERVERD PATH/.pid.daemon"
- X#define PID_SERVER PATH/.pid.server"
- X#define PID_LIST PATH/.pid.list"
- X#define CUT "cut"
- X#define AWK "awk" /* Do a 'which awk' for proper path */
- X#define UPTIME "uptime" /* 'which uptime' */
- X#define MAILER_DAEMON "MAILER|MAILER-DAEMON|MAILER-DEAMON|MAILER-DEMON|\
- DAEMON|DEAMON|DEMON|POSTMASTER|POST-MASTER|UUCP|ROOT"
- X /* Preserve upper case; put all possibilities above
- X separated by a '|'; all of the above entries will
- X be used to identify mailer daemon messages so
- X they can get special treatment */
- X#define UCB_MAIL "/usr/ucb/mail" /* Path to UCB mail program. Remove
- X it if UCB mail is not installed on your system,
- X in which case no mail is sent to MANAGER by 'serverd'
- X or when the programs receive various signals. */
- X
- X/*
- X These #define's should not be altered.
- X*/
- X
- X#define MAX_COMMANDS 15
- X#define KEEP_MESSAGE_IDS 500
- X#define DEFAULT_SERVER_ADDRESS "listserv"
- X#define DEFAULT_SERVER_CMDOPTIONS ""
- X#define DEFAULT_SERVER_COMMENT "Boston University List Server"
- X#define DEFAULT_MANAGER "server"
- X#define MAX_LINE 256
- X#define EOS '\0'
- X#define RESET(var) (var[0]) = EOS
- X#define BSD_PS 0x01
- X#define SYSV_PS 0x02
- X#define USE_TELNET 0x04
- X#define USE_ENV_VAR 0x08
- X#define USE_MY_SYSTEM 0x10
- X#define BSD_MAIL 0x20
- X#define POST_MAIL 0x40
- X#define GATE_MAIL 0x80
- X#define USE_SYSMAIL 0x100
- X#define LIMIT_MSG 0x200
- X#define START_OF_MESSAGE "From " /* UNIX mail messages start w/ this string */
- X#define ACK "ACK" /* Send message back to sender */
- X#define NOACK "NOACK" /* Do not send message back to sender */
- X#define POSTPONE "POSTPONE" /* Postpone sending mail */
- X#define MAX_SIGNAL NSIG /* Highest system signal caught */
- X#define BOOLEAN unsigned short int
- X#define TRUE 1
- X#define FALSE 0
- X#define SUBSCRIBED TRUE /* Subscribed sender */
- X#define NOTSUBSCRIBED FALSE /* Sender is not subscribed */
- X#define NEWS TRUE+1 /* News feed */
- X#define PEER TRUE+2
- X#define NEW_ARRIVAL "\n--- NEW MAIL HAS ARRIVED ---\n"
- X#define MAX_LISTS 10
- X#define SUBJECT "Subject: "
- X#define MESSAGE_ID1 "Message-Id: "
- X#define MESSAGE_ID2 "Message-ID: "
- X#define MESSAGE_ID3 "Message-id: "
- X
- X#define COMPLETE_TELNET(f) \
- X if (sys.options & USE_TELNET) \
- X COMPLETE_FILE (f)
- END_OF_FILE
- if test 4982 -ne `wc -c <'src/defs.h'`; then
- echo shar: \"'src/defs.h'\" unpacked with wrong size!
- fi
- # end of 'src/defs.h'
- fi
- if test -f 'src/sender.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/sender.c'\"
- else
- echo shar: Extracting \"'src/sender.c'\" \(6930 characters\)
- sed "s/^X//" >'src/sender.c' <<'END_OF_FILE'
- X/*
- X ----------------------------------------------------------------------------
- X | SENDER ORIENTED FUNCTIONS |
- X | |
- X | Version 2.0 |
- X | |
- X | (or, when Computer Science gets to you) |
- X | |
- X | Written by Anastasios Kotsikonas |
- X | (tasos@cs.bu.edu) |
- X | |
- X | AGREEMENT: This software can be used and distributed freely as long |
- X | as you do not remove or alter the Copyright notice in the file defs.h; |
- X | this notice is #define'd in the symbol VERSION. Although you may alter |
- X | the code provided, you may not alter the functions create_header() |
- X | and create_multi_recipient_header() in list.c and listserv.c. |
- X | By using this software you are bound by this agreement. |
- X | This software comes with no warranties and cannot be sold for profit. |
- X | The AGREEMENT and COPYRIGHT notices should be included in all source |
- X | files when distributing this software. |
- X | COPYRIGHT: Copyright (c) 1991, Anastasios C. Kotsikonas |
- X ----------------------------------------------------------------------------
- X*/
- X
- X#include <stdio.h>
- X#include <string.h>
- X#include <ctype.h>
- X#include "defs.h"
- X
- extern void report_progress (FILE *, char *, int);
- extern char *upcase (char *);
- extern void extract_subscriber (FILE *, char *);
- X
- BOOLEAN subscribed (FILE *, char *, char *, char *, char *, char *);
- BOOLEAN check_file (FILE *, char *, char *, BOOLEAN);
- BOOLEAN ignore_sender (FILE *, char *, FILE *);
- void extract_sender (char *);
- void extract_subscriber (FILE *f, char *subscriber);
- void extract_origin (char *);
- X
- X/*
- X Check if 'sender' is subscribed. Return SUBSCRIBED, NEWS PEER or
- X NOTSUBSCRIBED. Comparisons are done in upper case.
- X*/
- X
- BOOLEAN subscribed (FILE *report, char *sender, char *subscribersf,
- X char *newsf, char *peersf, char *aliasesf)
- X{
- X if (subscribersf == NULL) /* call made by distribute () in listserv.c */
- X return NOTSUBSCRIBED;
- X if (check_file (report, sender, subscribersf, FALSE) ||
- X check_file (report, sender, aliasesf, TRUE))
- X return SUBSCRIBED;
- X else if (newsf != NULL && (check_file (report, sender, newsf, FALSE) ||
- X check_file (report, sender, aliasesf, TRUE)))
- X return NEWS;
- X else if (peersf != NULL && (check_file (report, sender, peersf, FALSE) ||
- X check_file (report, sender, aliasesf, TRUE)))
- X return PEER;
- X return NOTSUBSCRIBED;
- X}
- X
- X/*
- X Check the given file for subscription. If the file is an aliases file
- X and the sender is listed in there, store his actual mailing address
- X in 'sender'.
- X*/
- X
- BOOLEAN check_file (FILE *report, char *sender, char *file,
- X BOOLEAN checking_aliases)
- X{
- X char subscriber [MAX_LINE];
- X char mode [MAX_LINE];
- X char name [MAX_LINE];
- X char error [MAX_LINE];
- X FILE *f;
- X
- X if ((f = fopen (file, "r")) == NULL)
- X RESET (error),
- X sprintf (error, "\ncheck_file(): Could not open %s", file),
- X report_progress (report, error, TRUE),
- X exit (1);
- X upcase (sender); /* Convert to upper case */
- X while (!feof (f)) { /* Check list of subscribers */
- X subscriber[0] = mode[0] = RESET (name);
- X extract_subscriber (f, subscriber);
- X fscanf (f, "%s ", mode);
- X if (!checking_aliases)
- X fgets (name, MAX_LINE - 2, f);
- X upcase (subscriber);
- X if (!strcmp (sender, subscriber)) {
- X fclose (f);
- X if (checking_aliases)
- X upcase (mode),
- X strcpy (sender, mode);
- X return SUBSCRIBED;
- X }
- X }
- X fclose (f);
- X return NOTSUBSCRIBED;
- X}
- X
- X/*
- X Check if 'sender' appears in the IGNORED file.
- X*/
- X
- BOOLEAN ignore_sender (FILE *ignored, char *sender, FILE *report)
- X{
- X char report_msg [MAX_LINE];
- X char ignored_user [MAX_LINE];
- X char line[MAX_LINE];
- X
- X rewind (ignored);
- X while (!feof (ignored)) { /* Check the IGNORED file first */
- X line[0] = RESET (ignored_user);
- X fgets (line, MAX_LINE - 2, ignored);
- X sscanf (line, "%s", ignored_user);
- X upcase (ignored_user);
- X if (ignored_user[0] != EOS)
- X if (!strcmp (ignored_user, sender)) {
- X RESET (report_msg);
- X sprintf (report_msg, "User %s and message ignored.\n", sender);
- X report_progress (report, report_msg, FALSE);
- X return TRUE;
- X }
- X }
- X return FALSE;
- X}
- X
- X/*
- X Extract the sender's email address. To do that, skip over the leading
- X "From ". That's where the address starts. Then put an EOS character at
- X the end of this address (a blank terminates this address string).
- X*/
- X
- void extract_sender (char *s)
- X{
- X int nsquote = 0, ndquote = 0, nparen = 0, nangle = 0, nsquare = 0;
- X BOOLEAN done = FALSE;
- X
- X sprintf (s, "%s", s + strlen (START_OF_MESSAGE));
- X while (*s && !done) { /* Look for end of address substring */
- X (*s == '\"' ? (nsquote ? (nsquote = 0) : (nsquote = 1)) : 0);
- X (*s == '\"' ? (ndquote ? (ndquote = 0) : (ndquote = 1)) : 0);
- X (*s == '(' ? ++nparen : 0);
- X (*s == ')' ? --nparen : 0);
- X (*s == '<' ? ++nangle : 0);
- X (*s == '>' ? --nangle : 0);
- X (*s == '[' ? ++nsquare : 0);
- X (*s == ']' ? --nsquare : 0);
- X ((*s == ' ' || *s == '\t') ?
- X ((nsquote || ndquote || nparen || nangle || nsquare) ?
- X 0 : (done = TRUE)) : 0);
- X ++s;
- X }
- X *(s - 1) = EOS; /* 's' is now pointing to the sender's address */
- X}
- X
- X/*
- X Extract the subscriber's address from the file.
- X*/
- X
- void extract_subscriber (FILE *f, char *subscriber)
- X{
- X int nsquote = 0, ndquote = 0, nparen = 0, nangle = 0, nsquare = 0, i = 0;
- X BOOLEAN done = FALSE;
- X char c;
- X
- X while (!feof (f) && !done) {
- X c = fgetc (f);
- X (c == '\"' ? (nsquote ? (nsquote = 0) : (nsquote = 1)) : 0);
- X (c == '\"' ? (ndquote ? (ndquote = 0) : (ndquote = 1)) : 0);
- X (c == '(' ? ++nparen : 0);
- X (c == ')' ? --nparen : 0);
- X (c == '<' ? ++nangle : 0);
- X (c == '>' ? --nangle : 0);
- X (c == '[' ? ++nsquare : 0);
- X (c == ']' ? --nsquare : 0);
- X ((c == ' ' || c == '\t') ?
- X ((nsquote || ndquote || nparen || nangle || nsquare) ?
- X 0 : (done = TRUE)) : 0);
- X subscriber [i++] = c;
- X }
- X if (i > 0)
- X subscriber[i - 1] = EOS;
- X}
- X
- X/*
- X Extract the originator of the message, i.e. the list that the original
- X message first originated from.
- X*/
- X
- void extract_origin (char *s)
- X{
- X char *p;
- X
- X if (p = strchr (s, '<'))
- X sprintf (s, "%s", p + 1); /* Remove '<' */
- X if (p = strchr (s, '>'))
- X *p = EOS; /* Remove '>' */
- X else { /* Get to the end of the address */
- X while (*s != EOS && !isspace (*s))
- X ++s;
- X *s = EOS;
- X }
- X}
- END_OF_FILE
- if test 6930 -ne `wc -c <'src/sender.c'`; then
- echo shar: \"'src/sender.c'\" unpacked with wrong size!
- fi
- # end of 'src/sender.c'
- fi
- if test -f 'src/serverd.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/serverd.c'\"
- else
- echo shar: Extracting \"'src/serverd.c'\" \(9491 characters\)
- sed "s/^X//" >'src/serverd.c' <<'END_OF_FILE'
- X/*
- X ----------------------------------------------------------------------------
- X | DISCUSSION LIST SYSTEM DAEMON |
- X | |
- X | Version 3.0 |
- X | |
- X | (or, when Computer Science gets to you) |
- X | |
- X | Written by Anastasios Kotsikonas |
- X | (tasos@cs.bu.edu) |
- X | |
- X | AGREEMENT: This software can be used and distributed freely as long |
- X | as you do not remove or alter the Copyright notice in the file defs.h; |
- X | this notice is #define'd in the symbol VERSION. Although you may alter |
- X | the code provided, you may not alter the functions create_header() in |
- X | list.c and listserv.c. By using this software you are bound by this |
- X | agreement. |
- X | This software comes with no warranties and cannot be sold for profit. |
- X | The AGREEMENT and COPYRIGHT notices should be included in all source |
- X | files when distributing this software. |
- X | COPYRIGHT: Copyright (c) 1991, Anastasios C. Kotsikonas |
- X ----------------------------------------------------------------------------
- X
- X Spawn list or listserv upon arrival of new messages. Send mail to
- X MANAGER if something went wrong (only if using UCB mail).
- X serverd will not spawn if the current load average is above max_load
- X and the -l flag is on, until it has delayed MAX_TRIES * 30 seconds.
- X serverd communicates with listerv via exit status 6 and 7; this are
- X the request to shutdwon/restart the system; on status 7, serverd spawns
- X start and dies; if it cannot restart, it sends mail and commits suicide.
- X serverd reports to REPORT_SERVERD.
- X
- X COMMAND LINE OPTIONS:
- X -1: Execute only once -- to be used with cron.
- X -l: Enforce restrictions based on the current load average.
- X -e: Echo reports to the screen.
- X
- X EXIT CODES:
- X 0: OK
- X 1: Could not open file
- X 2: Could not lock file
- X 3: Command line option error
- X 4: Syntax error in file
- X 5: Could not spawn
- X 6: Shutdown request
- X 7: Restart request
- X 8: Received system signal
- X 9: Too many multiple recipients
- X 10: Could not connect to server
- X 11: Server broke connection
- X 12: Could not create socket
- X 13: No such host
- X 14: Could not connect to port
- X 15: Connection timed out
- X 16: Malloc failed
- X*/
- X
- X#include <stdio.h>
- X#include <unistd.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <fcntl.h>
- X#include <signal.h>
- X#include "defs.h"
- X#include "serverd.h"
- X#include "struct.h"
- X#include "global.h"
- X
- X#ifdef __STDC__
- X#include <stdarg.h>
- extern int syscom (char *, ...);
- X#else
- X#include <varargs.h>
- extern int syscom ();
- X#endif
- extern double atof ();
- extern int sys_config (FILE *, SYS *);
- extern int getopt (int, char **, char *);
- extern void init_signals (void);
- extern void catch_signals (void);
- X
- void main (int, char **, char **);
- void serverd_config (char *alias);
- void usage (void);
- void gexit (void);
- X
- char *exit_string[] = { /* Define exit status strings */
- X/* 0 */ "OK",
- X/* 1 */ "Could not open file",
- X/* 2 */ "Could not lock file",
- X/* 3 */ "Command line option error",
- X/* 4 */ "Syntax error in file",
- X/* 5 */ "Could not spawn",
- X/* 6 */ "Shutdown request",
- X/* 7 */ "Restart request",
- X/* 8 */ "Received system signal",
- X/* 9 */ "Too many multiple recipients",
- X/* 10 */"Could not connect to server",
- X/* 11 */"Server broke connection",
- X/* 12 */"Could not create socket",
- X/* 13 */"No such host",
- X/* 14 */"Could not connect to port",
- X/* 15 */"Could not deliver mail",
- X/* 16 */"Malloc failed",
- X/* 17 */ "Unknown exit code"
- X};
- X
- void main (int argc, char **argv, char **envp)
- X{
- X struct stat stat_buf;
- X int i, status, try, fd, nlists;
- X FILE *f, *loadf, *report;
- X float load, max_load;
- X BOOLEAN loadr = FALSE, execute_once = FALSE;
- X char list [MAX_LINE];
- X char server [MAX_LINE];
- X char msg [MAX_LINE];
- X int c;
- X char *options = "1l:e";
- X extern char *optarg;
- X extern int optopt;
- X
- X while ((c = getopt (argc, argv, options)) != EOF)
- X switch ((char) c) {
- X case '1': execute_once = TRUE; break;
- X case 'e': tty_echo = TRUE; break;
- X case 'l': loadr = TRUE;
- X max_load = (float) atof (optarg);
- X break;
- X case ':':
- X fprintf (stderr, "serverd: Option '%c' requires an argument.\n",
- X optopt);
- X exit (3);
- X case '?':
- X default:
- X usage ();
- X }
- X#ifndef _MINIX
- X if (lockf ((fd = open (SERVERD_LOCK_FILE, O_RDWR)), F_TLOCK, 0))
- X fprintf (stderr, "serverd: Unable to lock %s. Aborting.\n",
- X SERVERD_LOCK_FILE),
- X exit (2);
- X#endif
- X if ((report = fopen (REPORT_SERVERD, "a")) == NULL)
- X fprintf (stderr, "serverd: Could not open %s\n", REPORT_SERVERD),
- X exit (1);
- X
- X if ((f = fopen (PID_SERVERD, "w")) != NULL)
- X fprintf (f, "%d", getpid()),
- X fclose (f);
- X signal (SIGINT, gexit);
- X init_signals();
- X catch_signals ();
- X
- X nlists = sys_config (report, &sys);
- X while (007) {
- X for (i = 0; i < nlists; ++i) {
- X serverd_config (sys.lists[i].alias);
- X if (!stat (list_mail_f, &stat_buf) && stat_buf.st_size > 0) {
- X sprintf (msg, "\n--- NEW MAIL FOR %s ---\n", sys.lists[i].alias);
- X report_progress (report, msg, FALSE);
- X if (loadr) { /* enforce restrictions */
- X try = 0;
- X again_list:
- X syscom ("%s | %s -F, '{ print $4 }' | %s -d' ' -f5 > %s",
- X UPTIME, AWK, CUT, LOAD_FILE);
- X if ((loadf = fopen (LOAD_FILE, "r")) == NULL)
- X sprintf (msg, "\nCould not open %s", LOAD_FILE),
- X report_progress (report, msg, TRUE),
- X exit (1);
- X fscanf (loadf, "%f", &load);
- X fclose (loadf);
- X unlink (LOAD_FILE);
- X if (load > max_load && try < MAX_TRIES) {
- X ++try;
- X sleep (30);
- X goto again_list;
- X }
- X }
- X RESET (list);
- X sprintf (list, "%s %s %s", LIST, sys.lists[i].alias,
- X sys.lists[i].cmdoptions);
- X report_progress (report, list, TRUE);
- X if ((status = system (list)) > 127) { /* run list */
- X sprintf (msg, "serverd died: LIST: %s", exit_string[status / 256]);
- X if (sys.options & BSD_MAIL)
- X syscom ("%s -s \"%s\" %s < /dev/null", UCB_MAIL, msg, sys.manager);
- X report_progress (report, msg, TRUE);
- X exit (status / 256);
- X }
- X else if (status == 127) {
- X sprintf (msg, "serverd died: could not execute shell for list");
- X if (sys.options & BSD_MAIL)
- X syscom ("%s -s \"%s\" %s < /dev/null", UCB_MAIL, msg, sys.manager);
- X report_progress (report, msg, TRUE);
- X exit (5);
- X }
- X }
- X if (sys.frequency > 0)
- X sleep (sys.frequency); /* do a quickie to The Spy Who Loved Him */
- X }
- X if (!stat (SERVER_MAIL_FILE, &stat_buf) && stat_buf.st_size > 0) {
- X report_progress (report, "\n--- NEW MAIL FOR SERVER ---\n", FALSE);
- X if (loadr) { /* Enforce restrictions */
- X try = 0;
- X again_server:
- X syscom ("%s | %s -F, '{ print $4 }' | %s -d' ' -f5 > %s",
- X UPTIME, AWK, CUT, LOAD_FILE);
- X if ((loadf = fopen (LOAD_FILE, "r")) == NULL)
- X sprintf (msg, "\nCould not open %s", LOAD_FILE),
- X report_progress (report, msg, TRUE),
- X exit (1);
- X fscanf (loadf, "%f", &load);
- X fclose (loadf);
- X unlink (LOAD_FILE);
- X if (load > max_load && try < MAX_TRIES) {
- X ++try;
- X sleep (30);
- X goto again_server;
- X }
- X }
- X RESET (server);
- X sprintf (server, "%s %s", SERVER, sys.server.cmdoptions);
- X report_progress (report, server, TRUE);
- X if ((status = system (server)) > 127) { /* run server */
- X sprintf (msg,"serverd died: LISTSERV: %s", exit_string[status / 256]);
- X if (sys.options & BSD_MAIL)
- X syscom ("%s -s \"%s\" %s < /dev/null", UCB_MAIL, msg, sys.manager);
- X report_progress (report, msg, TRUE);
- X if (status == 6 * 256) /* Shutdown request */
- X unlink (PID_SERVERD),
- X exit (6);
- X if (status == 7 * 256) { /* Restart request */
- X execl (START, START_OPTIONS, START_OPTIONS, NULL);
- X sprintf (msg, "serverd commits suicide: Could not restart system");
- X report_progress (report, msg, TRUE);
- X if (sys.options & BSD_MAIL)
- X syscom ("%s -s \"%s\" %s < /dev/null", UCB_MAIL, msg, sys.manager);
- X exit (5);
- X }
- X else
- X exit (status / 256);
- X }
- X else if (status == 127) {
- X sprintf (msg, "serverd died: could not execute shell for listserv");
- X if (sys.options & BSD_MAIL)
- X syscom ("%s -s \"%s\" %s < /dev/null", UCB_MAIL, msg, sys.manager);
- X report_progress (report, msg, TRUE);
- X exit (5);
- X }
- X }
- X if (execute_once)
- X gexit();
- X if (sys.frequency > 0)
- X sleep (sys.frequency); /* do a quickie to Money Penny */
- X }
- X}
- X
- void serverd_config (char *alias)
- X{
- X setup_string (list_mail_f, alias, LIST_MAIL_FILE);
- X}
- X
- void usage ()
- X{
- X fprintf (stderr, "Usage: serverd [-1] [-e] [-l load]\n\
- X-1: Execute only once.\n\
- X-e: Echo reports to the screen.\n\
- X-l: Enforce load restrictions.\n");
- X exit (3);
- X}
- X
- X/*
- X Graceful exit. Remove pid file.
- X*/
- X
- void gexit ()
- X{
- X unlink (PID_SERVERD);
- X exit (0);
- X}
- END_OF_FILE
- if test 9491 -ne `wc -c <'src/serverd.c'`; then
- echo shar: \"'src/serverd.c'\" unpacked with wrong size!
- fi
- # end of 'src/serverd.c'
- fi
- if test -f 'src/start.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/start.c'\"
- else
- echo shar: Extracting \"'src/start.c'\" \(12157 characters\)
- sed "s/^X//" >'src/start.c' <<'END_OF_FILE'
- X/*
- X ----------------------------------------------------------------------------
- X | DISCUSSION LIST SYSTEM HOUSEKEEPER |
- X | |
- X | Version 2.5 |
- X | |
- X | (or, when Computer Science gets to you) |
- X | |
- X | Written by Anastasios Kotsikonas |
- X | (tasos@cs.bu.edu) |
- X | |
- X | AGREEMENT: This software can be used and distributed freely as long |
- X | as you do not remove or alter the Copyright notice in the file defs.h; |
- X | this notice is #define'd in the symbol VERSION. Although you may alter |
- X | the code provided, you may not alter the functions create_header() |
- X | and create_multi_recipient_header() in list.c and listserv.c. |
- X | By using this software you are bound by this agreement. |
- X | This software comes with no warranties and cannot be sold for profit. |
- X | The AGREEMENT and COPYRIGHT notices should be included in all source |
- X | files when distributing this software. |
- X | COPYRIGHT: Copyright (c) 1991, Anastasios C. Kotsikonas |
- X ----------------------------------------------------------------------------
- X
- X This is the proper way of starting the discussion list. The program verifies
- X that no other serverd, list or listserv programs are running on the
- X system (and kills them before proceeding -- after confirming),
- X makes sure the required files exist (and creates new ones if missing --
- X after confirming), backs up all reports into files with extension .acc,
- X creates new directories for new discussion lists as necessary,
- X and finally spawns serverd. start reports to REPORT_START.
- X
- X COMMAND LINE OPTIONS:
- X -k: just kill all pertinent programs that may already be running; no
- X discussion list is started in this case.
- X -c: Do not confirm before killing a process.
- X -r: Do not report; useful when starting up when system is rebooted.
- X
- X WARNING: The program won't work correctly in the absence of an extended
- X egrep facility that does matching at the end of a line with a $ and
- X accepts multiple regular expressions separated by a |. In this case,
- X the user may have to manually look for and terminate any such programs.
- X Also when the output of the 'ps' command exceeds 80 characters (due perhaps
- X to long path names) the user may again have to terminate programs by hand.
- X Note that a file locking mechanism for serverd, list and listserv is used
- X to ensure against multiple executions of the same program.
- X
- X WARNING: When using the SYSV ps command and it chops output to 80 characters,
- X start may not be able to locate processes already running; this may occur if
- X the path to /usr/server is too long.
- X*/
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include "defs.h"
- X#include "start.h"
- X#include "struct.h"
- X#include "global.h"
- X
- X#define GET_RESPONSE {\
- X fflush (stdout); \
- X fflush (stdin); \
- X c = fgetc (stdin); \
- X if (c != '\n' && c != EOF) \
- X while (fgetc (stdin) != '\n'); \
- X fflush (stdin);\
- X }
- X
- X/*
- X Function prototypes:
- X*/
- X
- X#ifdef __STDC__
- X#include <stdarg.h>
- extern int syscom (char *, ...);
- X#else
- X#include <varargs.h>
- extern int syscom ();
- X#endif
- extern char *extract_filename (char *);
- extern void report_progress (FILE *, char *, int);
- extern int getopt (int, char **, char *);
- void main (int, char **);
- void check_for (char *, FILE *, BOOLEAN, BOOLEAN);
- void usage (void);
- void start_abort (void);
- void backup (char *, char *);
- void start_config (char *);
- X
- void main (int argc, char **argv)
- X{
- X char command [256];
- X char line [MAX_LINE];
- X char msg [2 * MAX_LINE];
- X char dir [MAX_LINE];
- X char *addr1, *addr2, *addr3, *addr4, *options = "ckr";
- X int c;
- X FILE *f, *p, *report;
- X int i, nlists, pid, procs_killed = 0, procs;
- X BOOLEAN just_kill = FALSE, confirm = TRUE, do_report = TRUE;
- X struct stat stat_buf;
- X extern char *optarg;
- X extern int optopt;
- X
- X while ((c = getopt (argc, argv, options)) != EOF)
- X switch ((char) c) {
- X case 'c': confirm = FALSE; break;
- X case 'k': just_kill = TRUE; break;
- X case 'r': do_report = FALSE; break;
- X case '?':
- X default:
- X usage();
- X }
- X
- X /* First make sure no other SERVERD programs are running. If so, kill
- X them all (after confirming) before proceeding. */
- X
- X backup (REPORT_START, REPORT_START_ACC);
- X if ((report = fopen (REPORT_START, "a")) == NULL)
- X fprintf (stderr, "start: Could not open %s\n", REPORT_START),
- X start_abort();
- X nlists = sys_config (report, &sys);
- X if (just_kill)
- X report_progress (report, "\n--- SHUTTING LISTSERV SYSTEM DOWN ---\n",FALSE);
- X else
- X report_progress (report, "\n--- STARTING LISTSERV SYSTEM ---\n", FALSE);
- X#ifndef _MINIX
- X if (sys.options & BSD_PS)
- X syscom ("ps -gx > /tmp/ps"); /* do not combine the two "syscom"'s */
- X else
- X syscom ("ps -ef | grep %s > /tmp/ps", getenv ("LOGNAME"));
- X tty_echo = FALSE;
- X syscom ("egrep '%s$|%s|%s$|%s |%s$|%s |%s|%s |queued' /tmp/ps > /tmp/found",
- X (addr1 = extract_filename (SERVERD)), addr1,
- X (addr2 = extract_filename (LIST)), addr2,
- X (addr3 = extract_filename (SERVER)), addr3,
- X (addr4 = extract_filename (PQUEUE)), addr4);
- X free ((char *) addr1);
- X free ((char *) addr2);
- X free ((char *) addr3);
- X free ((char *) addr4);
- X unlink ("/tmp/ps");
- X tty_echo = TRUE;
- X if ((f = fopen ("/tmp/found", "r")) == NULL)
- X sprintf (msg, "Error opening /tmp/found. Aborting. %s",
- X ((just_kill == FALSE) ? "No discussion list started." : "")),
- X report_progress (report, msg, TRUE),
- X start_abort ();
- X
- X syscom ("wc -l /tmp/found > /tmp/nprocs");
- X if ((p = fopen ("/tmp/nprocs", "r")) != NULL) {
- X fscanf (p, "%d", &procs);
- X if (do_report)
- X sprintf (msg, "OLD LISTSERV PROCESSES RUNNING:\t%d\n", procs),
- X report_progress (report, msg, FALSE);
- X fclose (p);
- X unlink ("/tmp/nprocs");
- X }
- X else
- X sprintf (msg, "Error opening /tmp/nprocs. Aborting. %s",
- X ((just_kill == FALSE) ? "No discussion list started." : "")),
- X report_progress (report, msg, TRUE),
- X start_abort ();
- X
- X while (!feof (f)) { /* get pid's and kill processes after confirming */
- X RESET (line);
- X fgets (line, MAX_LINE - 2, f);
- X if (line[0] != EOS) {
- X if (sys.options & BSD_PS)
- X sscanf (line, "%d ", &pid);
- X else
- X sscanf (line, "%s %d ", command, &pid);
- X if (confirm) {
- X c = EOS;
- X while (c != EOF && c != 'Y' && c != 'N') {
- X sprintf (msg, "\n%s\n%c[7m%s%c[mKill it to proceed ? (Y/N) ",
- X ((just_kill == FALSE) ?
- X "ERROR: another listserv-system program running:" :
- X "Listserv-system program found:"),
- X 27, line, 27);
- X report_progress (report, msg, FALSE);
- X GET_RESPONSE;
- X }
- X if (c == 'N' || c == EOF)
- X sprintf (msg, "start aborted. %s\n",
- X ((just_kill == FALSE) ? "System not started.":"")),
- X report_progress (report, msg, TRUE),
- X exit (1);
- X }
- X kill (pid, SIGINT);
- X ++procs_killed;
- X }
- X }
- X fclose (f);
- X unlink ("/tmp/found");
- X if ((f = fopen (PID_SERVERD, "r")) != NULL)
- X fscanf (f, "%d", &pid),
- X kill (pid, SIGINT),
- X ++procs_killed,
- X fclose (f),
- X unlink (PID_SERVERD);
- X if ((f = fopen (PID_LIST, "r")) != NULL)
- X fscanf (f, "%d", &pid),
- X kill (pid, SIGINT),
- X ++procs_killed,
- X fclose (f),
- X unlink (PID_LIST);
- X if ((f = fopen (PID_SERVER, "r")) != NULL)
- X fscanf (f, "%d", &pid),
- X kill (pid, SIGINT),
- X ++procs_killed,
- X fclose (f),
- X unlink (PID_SERVER);
- X if ((f = fopen (PID_PQUEUE, "r")) != NULL)
- X fscanf (f, "%d", &pid),
- X kill (pid, SIGINT),
- X ++procs_killed,
- X fclose (f),
- X unlink (PID_PQUEUE);
- X if (do_report)
- X sprintf (msg, "OLD LISTSERV PROCESSES KILLED:\t%d\n", procs_killed),
- X report_progress (report, msg, FALSE);
- X
- X if (just_kill) /* Done */
- X report_progress (report, "", -TRUE),
- X fclose (report),
- X exit (0);
- X#endif
- X
- X syscom ("echo Serverd lock file > %s", SERVERD_LOCK_FILE);
- X syscom ("echo List lock file > %s", LIST_LOCK_FILE);
- X syscom ("echo Server lock file > %s", SERVER_LOCK_FILE);
- X syscom ("echo Pqueue lock file > %s", PQUEUE_LOCK_FILE);
- X
- X backup (REPORT_SERVER, REPORT_SERVER_ACC);
- X backup (REPORT_SERVERD, REPORT_SERVERD_ACC);
- X backup (REPORT_PQUEUE, REPORT_PQUEUE_ACC);
- X sprintf (server_ignoredf, "%s/%s", PATH", IGNORED);
- X check_for (server_ignoredf, report, do_report, confirm);
- X for (i = 0; i < nlists; ++i) {
- X start_config (sys.lists[i].alias);
- X sprintf (dir, "%s/lists/%s", PATH", sys.lists[i].alias);
- X if (stat (dir, &stat_buf)) {
- X if (mkdir (dir, 475))
- X sprintf (msg, "Could not create directory %s", dir),
- X report_progress (report, msg, TRUE),
- X start_abort ();
- X syscom ("chmod 733 %s", dir);
- X if (do_report)
- X sprintf (msg, "*** New list %s ***\n", sys.lists[i].alias),
- X report_progress (report, msg, FALSE);
- X syscom ("cp %s %s", server_ignoredf, dir);
- X syscom ("echo %s >> %s/%s", sys.lists[i].alias, dir, IGNORED);
- X syscom ("echo %s >> %s/%s", sys.lists[i].address, dir, IGNORED);
- X syscom ("echo %s | sed 's/listserv/server/' >> %s/%s", sys.server.address,
- X dir, IGNORED);
- X syscom ("touch %s", infof);
- X syscom ("touch %s", welcomef);
- X syscom ("touch %s/%s", dir, LIST_MAIL_FILE);
- X syscom ("chmod 666 %s/%s", dir, LIST_MAIL_FILE);
- X syscom ("touch %s/%s", dir, MODERATED_MAIL_FILE);
- X syscom ("chmod 666 %s/%s", dir, MODERATED_MAIL_FILE);
- X }
- X check_for (subscribersf, report, do_report, confirm);
- X check_for (aliasesf, report, do_report, confirm);
- X check_for (newsf, report, do_report, confirm);
- X check_for (peersf, report, do_report, confirm);
- X check_for (restrictedf, report, do_report, confirm);
- X backup (report_listf, report_list_accf);
- X }
- X syscom ("%s %s &", SERVERD, sys.serverd_cmdoptions);
- X report_progress (report, "", -TRUE);
- X fclose (report);
- X exit (0);
- X}
- X
- X/*
- X Make sure that file 's' exists. Create a new one if necessary.
- X*/
- X
- void check_for (char *s, FILE *report, BOOLEAN do_report, BOOLEAN confirm)
- X{
- X char c = EOS, msg [MAX_LINE];
- X struct stat stat_buf;
- X
- X if (stat (s, &stat_buf)) { /* make sure we have file 's' */
- X if (confirm) {
- X while (c != EOF && c != 'Y' && c != 'N') {
- X if (do_report)
- X sprintf (msg, "No %s file found. Create a new one? (Y/N) ", s),
- X report_progress (report, msg, FALSE);
- X GET_RESPONSE;
- X }
- X if (c == 'N' || c == EOF)
- X start_abort ();
- X }
- X syscom ("touch %s", s);
- X }
- X}
- X
- X/*
- X Append 'src' to 'dest' and create a brand new 'src'.
- X*/
- X
- void backup (char *src, char *dest)
- X{
- X struct stat stat_buf;
- X
- X if (!stat (src, &stat_buf)) /* prepare for backup */
- X syscom ("cat %s >> %s", src, dest),
- X unlink (src),
- X syscom ("touch %s", src);
- X}
- X
- X/*
- X Print usage.
- X*/
- X
- void usage ()
- X{
- X fprintf (stderr, "Usage: start [-k] [-c] [-r]\n\
- X-k: Just kill any listserv-system programs running.\n\
- X-c: Do not confirm before killing processes.\n\
- X-r: Restrict reporting to screen.\n");
- X exit (1);
- X}
- X
- X/*
- X Abort after printing a message.
- X*/
- X
- void start_abort ()
- X{
- X fprintf (stderr, "### start aborted; discussion list not started. ###\n");
- X exit (1);
- X}
- X
- void start_config (char *alias)
- X{
- X setup_string (subscribersf, alias, SUBSCRIBERS);
- X setup_string (aliasesf, alias, ALIASES);
- X setup_string (newsf, alias, NEWSF);
- X setup_string (peersf, alias, PEERS);
- X setup_string (restrictedf, alias, RESTRICTED);
- X setup_string (ignoredf, alias, IGNORED);
- X setup_string (report_listf, alias, REPORT_LIST);
- X setup_string (infof, alias, INFO_FILE);
- X setup_string (welcomef, alias, WELCOME_FILE);
- X setup_string (report_list_accf, alias, REPORT_LIST_ACC);
- X}
- END_OF_FILE
- if test 12157 -ne `wc -c <'src/start.c'`; then
- echo shar: \"'src/start.c'\" unpacked with wrong size!
- fi
- # end of 'src/start.c'
- fi
- if test -f 'src/sysmail.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/sysmail.c'\"
- else
- echo shar: Extracting \"'src/sysmail.c'\" \(6501 characters\)
- sed "s/^X//" >'src/sysmail.c' <<'END_OF_FILE'
- X/*
- X ----------------------------------------------------------------------------
- X | SYSTEM MAILING ROUTINES |
- X | |
- X | Version 1.0 |
- X | |
- X | (or, when Computer Science gets to you) |
- X | |
- X | Written by Anastasios Kotsikonas |
- X | (tasos@cs.bu.edu) |
- X | |
- X | AGREEMENT: This software can be used and distributed freely as long |
- X | as you do not remove or alter the Copyright notice in the file defs.h; |
- X | this notice is #define'd in the symbol VERSION. Although you may alter |
- X | the code provided, you may not alter the functions create_header() |
- X | and create_multi_recipient_header() in list.c and listserv.c. |
- X | By using this software you are bound by this agreement. |
- X | This software comes with no warranties and cannot be sold for profit. |
- X | The AGREEMENT and COPYRIGHT notices should be included in all source |
- X | files when distributing this software. |
- X | COPYRIGHT: Copyright (c) 1991, Anastasios C. Kotsikonas |
- X ----------------------------------------------------------------------------
- X
- X These routines implement the 'system' mailmethod. The system opens a socket
- X and connects directly with sendmail for mail delivery. During the process
- X of porting the code to various platforms, lots of grosse things were
- X encountered with sockets and protocols, so the code may seem kludgy.
- X
- X When mail cannot be sent due to network problems, it is queued up and will
- X be delivered later by the queue daemon.
- X*/
- X
- X#include <stdio.h>
- X#include <string.h>
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <netdb.h>
- X#include "defs.h"
- X#include "struct.h"
- X#include "sysmail.h"
- X
- X#ifdef __STDC__
- X#include <stdarg.h>
- extern int syscom (char *, ...);
- X#else
- X#include <varargs.h>
- extern int syscom ();
- X#endif
- extern FILE *report;
- extern SYS sys;
- extern BOOLEAN debug;
- X
- extern void report_progress (FILE *, char *, int);
- X
- BOOLEAN sysmail (char *);
- BOOLEAN _sysmail (char *, int);
- int server_response (int, FILE *);
- int build_tcp_connection (FILE *);
- void queue_up (char *file);
- X
- X/*
- X The return value depends on the return value of _sysmail ().
- X*/
- X
- BOOLEAN sysmail (char *file)
- X{
- X char error [MAX_LINE];
- X
- X queue = FALSE;
- X if (debug) {
- X if ((sent = fopen (SENT, "w")) == NULL)
- X sprintf (error, "\nsysmail(): Could not open %s", SENT),
- X report_progress (report, error, TRUE),
- X exit (1);
- X if ((received = fopen (RECEIVED, "w")) == NULL)
- X sprintf (error, "\nsysmail(): Could not open %s", RECEIVED),
- X report_progress (report, error, TRUE),
- X exit (1);
- X }
- X return _sysmail (file, 1);
- X}
- X
- X/*
- X 'system' mailmethod. It returns TRUE if the mail was successfully
- X delivered, FALSE if it was queued.
- X*/
- X
- BOOLEAN _sysmail (char *file, int call)
- X{
- X char buf [MAX_LINE] ;
- X char error [MAX_LINE];
- X FILE *msg;
- X int sock_fd, cmd, timeout;
- X
- X if ((msg = fopen (file, "r")) == NULL)
- X sprintf (error, "\n_sysmail(): Could not open %s", file),
- X report_progress (report, error, TRUE),
- X exit (1);
- X sock_fd = build_tcp_connection (report);
- X if ((cmd = server_response (sock_fd, report)) != ACKNOWLEDGE) {
- X report_progress (report, "\n_sysmail(): Could not connect to server", TRUE);
- X queue = TRUE;
- X goto abort;
- X }
- X
- X PROTOCOL (DATA);
- X while (!feof (msg) && strcmp (buf, END_OF_TEXT)) { /* Copy header and text */
- X RESET (buf);
- X fgets (buf, MAX_LINE - 2, msg);
- X write (sock_fd, buf, strlen (buf));
- X if (debug)
- X fprintf (sent, "%s", buf),
- X fflush (sent);
- X }
- X cmd = server_response (sock_fd, report);
- X PROTOCOL (CLOSE_CONNECTION);
- X abort:
- X if (queue)
- X queue_up (file);
- X CLOSEF;
- X if (debug)
- X fclose (sent),
- X fclose (received);
- X if (queue)
- X return FALSE;
- X else
- X return TRUE;
- X}
- X
- X/*
- X Get server response. Return the command number that the server sent.
- X*/
- X
- int server_response (int sock_fd, FILE *report)
- X{
- X char buf [MAX_LINE];
- X int cmd, i;
- X
- X if (read (sock_fd, buf, 3) < 0) /* Get server command */
- X report_progress (report, "\nserver_response(): Server dropped connection",
- X TRUE),
- X exit (11);
- X RESET (message);
- X buf[3] = EOS;
- X cmd = atoi (buf);
- X sprintf (message, "%s", buf);
- X i = strlen (message);
- X if (debug)
- X fprintf (received, "%s", buf),
- X fflush (received);
- X while (buf[0] != '\n') { /* Read till the end of socket */
- X if (read (sock_fd, buf, 1) < 1) {
- X if (debug)
- X fprintf (received, "%s", buf),
- X fflush (received);
- X message [i] = EOS;
- X break;
- X }
- X message [i++] = (buf[0] != '\n' ? buf[0] : EOS);
- X if (debug)
- X fprintf (received, "%c", buf[0]),
- X fflush (received);
- X }
- X return cmd;
- X}
- X
- X/*
- X Establish connection with sendmail/smtp.
- X*/
- X
- int build_tcp_connection (FILE *report)
- X{
- X int sock_fd;
- X struct sockaddr_in sin;
- X struct hostent *hostentry;
- X
- X if ((sock_fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
- X report_progress (report, "\nbuild_tcp_connection(): Could not create \
- socket", TRUE),
- X exit(12);
- X if (! (hostentry = gethostbyname ("localhost")))
- X report_progress (report, "\nbuild_tcp_connection(): No such host", TRUE),
- X exit(13);
- X sin.sin_family = AF_INET;
- X sin.sin_port = htons (PORT);
- X memcpy ((char *) &sin.sin_addr.s_addr, (char *) hostentry->h_addr,
- X hostentry->h_length);
- X memset (sin.sin_zero, EOS, sizeof (sin.sin_zero));
- X if (connect (sock_fd, (struct sockaddr *) &sin, sizeof (struct sockaddr_in))
- X < 0)
- X report_progress (report, "\nbuild_tcp_connection(): Could not connect to \
- port", TRUE),
- X exit (14);
- X return sock_fd;
- X}
- X
- X/*
- X Queue up a file for later delivery.
- X*/
- X
- void queue_up (char *file)
- X{
- X FILE *id;
- X int id_no = 0;
- X char msg [MAX_LINE];
- X
- X if ((id = fopen (IDF, "r")) != NULL)
- X fscanf (id, "%d\n", &id_no),
- X fclose (id);
- X syscom ("mv %s %s/%d", file, QUEUE_DIR, ++id_no);
- X syscom ("echo %d > %s", id_no, IDF);
- X sprintf (msg, "File %s placed in the mail queue", file);
- X report_progress (report, msg, TRUE);
- X}
- END_OF_FILE
- if test 6501 -ne `wc -c <'src/sysmail.c'`; then
- echo shar: \"'src/sysmail.c'\" unpacked with wrong size!
- fi
- # end of 'src/sysmail.c'
- fi
- if test -f 'src/sysmail.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/sysmail.h'\"
- else
- echo shar: Extracting \"'src/sysmail.h'\" \(6146 characters\)
- sed "s/^X//" >'src/sysmail.h' <<'END_OF_FILE'
- X/*
- X AGREEMENT: This software can be used and distributed freely as long
- X as you do not remove or alter the Copyright notice in the file defs.h;
- X this notice is #define'd in the symbol VERSION. Although you may alter
- X the code provided, you may not alter the functions create_header()
- X and create_multi_recipient_header() in list.c and listserv.c.
- X By using this software you are bound by this agreement.
- X This software comes with no warranties and cannot be sold for profit.
- X The AGREEMENT and COPYRIGHT notices should be included in all source
- X files when distributing this software.
- X COPYRIGHT: Copyright (c) 1991, Anastasios C. Kotsikonas
- X*/
- X
- X#define PORT 25
- X#define TIMEOUT 10
- X#define MAX_CALLS 1
- X#define SENT PATH/sent"
- X#define RECEIVED PATH/received"
- X#define IDF PATH/.queue.id"
- X#define QUEUE_DIR PATH/mqueue"
- X
- X/* List of SMTP commands recognized */
- X
- X#define ACKNOWLEDGE 220
- X#define CLOSE_CONNECTION 221
- X#define OK 250
- X#define WILL_FORWARD 251
- X#define DATA 354
- X#define SERVICE_UNAVAIL 421
- X#define PERMISSION_DENIED 450
- X#define HOST_ABORTED 451
- X#define DISK_FULL 452
- X#define NOT_RECOGNIZED 500
- X#define SYNTAX_ERROR 501
- X#define BAD_SEQUENCE 503
- X#define USER_UNKNOWN 550
- X#define USER_NOT_LOCAL 551
- X#define TOO_MUCH_DATA 552
- X#define USER_AMBIGUOUS 553
- X#define TRANS_FAILED 554
- X#define END_OF_TEXT ".\n"
- X
- X#define CLOSEF \
- X fclose (msg),\
- X close (sock_fd)
- X
- X#define NOTIFY_MANAGER \
- X if (sys.options & BSD_MAIL)\
- X syscom ("%s -s \"Error during message delivery: check the report \
- files\" %s &", UCB_MAIL, sys.manager);\
- X
- X#define WARN_MANAGER \
- X if (sys.options & BSD_MAIL)\
- X syscom ("%s -s \"Warning during message delivery: check the report \
- files\" %s &", UCB_MAIL, sys.manager);\
- X
- X#define ABORT_CONNECTION \
- X if (write (sock_fd, "QUIT\n", 5) < 5)\
- X report_progress (report, "_sysmail(): WARNING: Error writing to \
- socket, while closing connection", TRUE);\
- X if (debug)\
- X fprintf (sent, "QUIT\n"),\
- X fflush (sent);\
- X cmd = server_response (sock_fd, report);
- X
- X#define PROTOCOL(arg) \
- X while (!feof (msg) && cmd != arg) {\
- X RESET (buf);\
- X fgets (buf, MAX_LINE - 2, msg);\
- X if (write (sock_fd, buf, strlen (buf)) < strlen (buf))\
- X report_progress (report, "_sysmail(): WARNING: Error writing to \
- socket, trying again", TRUE);\
- X if (debug)\
- X fprintf (sent, "%s", buf),\
- X fflush (sent);\
- X cmd = server_response (sock_fd, report);\
- X timeout = 0;\
- X while (cmd != OK && cmd != arg && timeout < TIMEOUT) {\
- X ++timeout;\
- X if (write (sock_fd, buf, strlen (buf)) < strlen (buf))\
- X report_progress (report, "_sysmail(): WARNING: Error rewriting to \
- socket", TRUE);\
- X if (debug)\
- X fprintf (sent, "%s", buf),\
- X fflush (sent);\
- X cmd = server_response (sock_fd, report);\
- X }\
- X if (timeout == TIMEOUT) {\
- X char error [1024];\
- X if (cmd == SYNTAX_ERROR || cmd == TRANS_FAILED ||\
- X cmd == NOT_RECOGNIZED) {\
- X sprintf (error, "_sysmail(): Command: %snot recognized by sendmail.\
- X\n%s\nCould not deliver mail", buf, message);\
- X report_progress (report, error, TRUE);\
- X NOTIFY_MANAGER;\
- X ABORT_CONNECTION;\
- X CLOSEF;\
- X exit (15);\
- X }\
- X else if (cmd == BAD_SEQUENCE) {\
- X sprintf (error, "_sysmail(): Command: %sissued too soon.\
- X\n%s\nCould not deliver mail", buf, message);\
- X report_progress (report, error, TRUE);\
- X NOTIFY_MANAGER;\
- X ABORT_CONNECTION;\
- X CLOSEF;\
- X exit (15);\
- X }\
- X else if (cmd == SERVICE_UNAVAIL || cmd == HOST_ABORTED) {\
- X sprintf (error, "_sysmail(): Service unavailable.\
- X\n%s\nCould not deliver mail", message);\
- X report_progress (report, error, TRUE);\
- X NOTIFY_MANAGER;\
- X ABORT_CONNECTION;\
- X queue = TRUE;\
- X goto abort;\
- X }\
- X else if (cmd == DISK_FULL) {\
- X sprintf (error, "_sysmail(): File system full.\n%s\nCould not \
- deliver mail", message);\
- X report_progress (report, error, TRUE);\
- X NOTIFY_MANAGER;\
- X ABORT_CONNECTION;\
- X queue = TRUE;\
- X goto abort;\
- X }\
- X else if (cmd == TOO_MUCH_DATA) {\
- X sprintf (error, "_sysmail(): Too many recipients or message \
- too long.\n%s\nCould not deliver mail", message);\
- X report_progress (report, error, TRUE);\
- X NOTIFY_MANAGER;\
- X ABORT_CONNECTION;\
- X CLOSEF;\
- X exit (15);\
- X }\
- X else if (cmd == USER_UNKNOWN) {\
- X sprintf (error, "_sysmail(): Address: %snot recognized.\n%s\nMessage \
- not delivered to this recipient", buf, message);\
- X report_progress (report, error, TRUE);\
- X WARN_MANAGER;\
- X continue;\
- X }\
- X else if (cmd == USER_NOT_LOCAL) {\
- X sprintf (error, "_sysmail(): Address: %snot local; %s", buf, message);\
- X report_progress (report, error, TRUE);\
- X WARN_MANAGER;\
- X continue;\
- X }\
- X else if (cmd == USER_AMBIGUOUS) {\
- X sprintf (error, "_sysmail(): Address ambiguous: %s%s\nMessage not \
- delivered to this address", buf, message);\
- X report_progress (report, error, TRUE);\
- X WARN_MANAGER;\
- X continue;\
- X }\
- X else if (cmd == PERMISSION_DENIED) {\
- X sprintf (error, "_sysmail(): Permission denied for address %s%s\n\
- Message not delivered to this recipient", buf, message);\
- X report_progress (report, error, TRUE);\
- X WARN_MANAGER;\
- X continue;\
- X }\
- X else if (cmd == WILL_FORWARD) {\
- X sprintf (error, "_sysmail(): Address: %snot local; %s", buf, message);\
- X report_progress (report, error, TRUE);\
- X WARN_MANAGER;\
- X continue;\
- X }\
- X sprintf (error, "_sysmail(): ERROR: Return value %d for command: %s%s\n\
- Please notify tasos@cs.bu.edu", cmd, buf, message);\
- X report_progress (report, error, TRUE);\
- X NOTIFY_MANAGER;\
- X if (call < MAX_CALLS)\
- X CLOSEF,\
- X sleep (60),\
- X _sysmail (file, call + 1);\
- X report_progress (report, "_sysmail(): ERROR: Could not deliver mail", \
- TRUE);\
- X CLOSEF,\
- X exit (15);\
- X }\
- X }
- X
- static char message [1024];
- static FILE *sent, *received;
- static BOOLEAN queue;
- END_OF_FILE
- if test 6146 -ne `wc -c <'src/sysmail.h'`; then
- echo shar: \"'src/sysmail.h'\" unpacked with wrong size!
- fi
- # end of 'src/sysmail.h'
- fi
- echo shar: End of archive 2 \(of 6\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 4 5 6 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 6 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-